package com.easyedu.selection.service;

import com.alibaba.fastjson.JSONObject;
import com.easyedu.core.entity.po.OpenCourse;
import com.easyedu.core.entity.po.StudentSelect;
import com.easyedu.core.exception.EasyEduException;
import com.easyedu.core.redis.RedisUtils;
import com.easyedu.core.util.BuildRedisKey;
import com.easyedu.core.util.R;
import com.easyedu.selection.dao.CourseSelectionDao;
import com.easyedu.selection.entity.dto.request.ReqDropCourse;
import com.easyedu.selection.entity.dto.request.ReqSelectCourse;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * @author lmr
 **/
@Service
public class CourseSelectionService {

    private final RedisUtils redisUtils;

    private final CourseSelectionDao courseSelectionDao;

    public CourseSelectionService(RedisUtils redisUtils, CourseSelectionDao courseSelectionDao) {
        this.redisUtils = redisUtils;
        this.courseSelectionDao = courseSelectionDao;
    }

    public List<String> getCanSelection(Long instituteId, Long departmentId, Integer openYear) {
        List<String> courseMsg = redisUtils.lRange(BuildRedisKey.buildCourseSelection(instituteId, departmentId, openYear), 0, -1);
        if (courseMsg == null || courseMsg.isEmpty()) {
            throw new EasyEduException(1999, "没有可选课程");
        }
        return courseMsg;
    }

    @Transactional(rollbackFor = Exception.class)
    public R selectCourse(ReqSelectCourse reqSelectCourse) {
        Long studentNumber = reqSelectCourse.getStudentNumber();
        String courseNumber = reqSelectCourse.getCourseNumber();
        String courseCapacityKey = BuildRedisKey.buildCourseCapacity(courseNumber);
        if (!redisUtils.hasKey(courseCapacityKey)) {
            return R.error().message("无此课程");
        }
        Long decr = redisUtils.decrBy(courseCapacityKey);
        if (decr <= 0) {
            redisUtils.incrBy(courseCapacityKey);
            return R.error().message("选课失败，课程容量不足");
        }
        //查询学生是否已经选择此课程
        List<String> studentSelectionCourses = redisUtils.lRange(BuildRedisKey.buildStudentSelection(studentNumber),
                0, -1);
        studentSelectionCourses.parallelStream().forEach(studentSelectionCourse -> {
            OpenCourse openCourse = JSONObject.parseObject(studentSelectionCourse, OpenCourse.class);
            if (openCourse != null && openCourse.getCourseNumber().equals(courseNumber)) {
                throw new EasyEduException(1999, "您已选择此课程");
            }
        });
        //在课程下添加选课学生信息（缓存）
        redisUtils.lLeftPush(BuildRedisKey.buildCourseStudentList(courseNumber), String.valueOf(studentNumber));

        //在学生下添加已选课程（缓存）
        String courseJson = redisUtils.get(BuildRedisKey.buildCourse(courseNumber));
        redisUtils.lLeftPush(BuildRedisKey.buildStudentSelection(studentNumber), courseJson);
        //数据库中查询是否已选此课程
        List<StudentSelect> studentSelects = courseSelectionDao.getByStudentNumberAndCourseNumber(studentNumber, courseNumber);
        if (studentSelects != null && !studentSelects.isEmpty()) {
            return R.error().message("您已选择此课程");
        }
        //数据库中添加学生选课信息
        Integer integer = courseSelectionDao.setStudentCourse(studentNumber, courseNumber);
        if (integer != 1) {
            throw new EasyEduException(1999, "选课失败，请重试");
        }
        return R.ok().message("选课成功");
    }

    @Transactional(rollbackFor = Exception.class)
    public R deSelectCourse(ReqDropCourse reqDropCourse) {
        Long studentNumber =reqDropCourse.getStudentNumber();
        String courseNumber = reqDropCourse.getCourseNumber();
        String courseCapacityKey = BuildRedisKey.buildCourseCapacity(courseNumber);
        if (!redisUtils.hasKey(courseCapacityKey)) {
            return R.error().message("无此课程");
        }
        //查询学生是否已经选择此课程
        boolean flag = false;
        List<String> studentSelectionCourses = redisUtils.lRange(BuildRedisKey.buildStudentSelection(studentNumber),
                0, -1);
        String openCourseStr = null;
        for (String studentSelectionCourse : studentSelectionCourses) {
            OpenCourse openCourse = JSONObject.parseObject(studentSelectionCourse, OpenCourse.class);
            if (openCourse != null && openCourse.getCourseNumber().equals(courseNumber)) {
                openCourseStr = studentSelectionCourse;
                flag = true;
                break;
            }
        }
        if (!flag) {
            return R.error().message("您未选择此课程");
        }
        redisUtils.lRemove(BuildRedisKey.buildCourseStudentList(courseNumber), 0, String.valueOf(studentNumber));
        redisUtils.lRemove(BuildRedisKey.buildStudentSelection(studentNumber), 0, openCourseStr);
        Integer integer = courseSelectionDao.deleteByStudentNumberAndCourseNumber(studentNumber, courseNumber);
        if (integer != 1) {
            throw new EasyEduException(1999, "退课失败，请重试");
        }
        redisUtils.incrBy(BuildRedisKey.buildCourseCapacity(courseNumber));
        return R.ok().message("退课成功");
    }

    public List<OpenCourse> getHasSelection(Long studentNumber) {
        List<String> strings = redisUtils.lRange(BuildRedisKey.buildStudentSelection(studentNumber), 0, -1);
        List<OpenCourse> openCourseList = new ArrayList<>();
        for (String string : strings) {
            OpenCourse openCourse = JSONObject.parseObject(string, OpenCourse.class);
            openCourseList.add(openCourse);
        }
        return openCourseList;
    }
}
